///**
// * Project Name:spring-config-client
// * File Name:DynamicDeployBeans2.java
// * Package Name:org.spring.config.client.dynamic
// * Date:2019年11月5日下午4:00:03
// * Copyright (c) 2019, dengqian37@126.com All Rights Reserved.
// *
// */
//
//package org.spring.config.client.dynamic;
///**
// * ClassName:DynamicDeployBeans2 <br/>
// * Function: TODO ADD FUNCTION. <br/>
// * Reason: TODO ADD REASON. <br/>
// * Date: 2019年11月5日 下午4:00:03 <br/>
// * @author dengqian
// * @version
// * @since JDK 1.8
// * @see
// */
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.beans.factory.config.BeanDefinition;
//import org.springframework.beans.factory.config.ConstructorArgumentValues;
//import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
//import org.springframework.beans.factory.support.DefaultListableBeanFactory;
//import org.springframework.beans.factory.support.GenericBeanDefinition;
//import org.springframework.beans.factory.support.RootBeanDefinition;
//import org.springframework.context.ApplicationContext;
//import org.springframework.scripting.groovy.GroovyScriptFactory;
//import org.springframework.scripting.support.ScriptFactoryPostProcessor;
//import org.springframework.util.*;
//import org.springframework.web.context.WebApplicationContext;
//import org.springframework.web.method.HandlerMethodSelector;
//import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
//import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
//
//import java.lang.reflect.Field;
//import java.lang.reflect.Method;
//import java.util.Map;
//import java.util.Set;
//
///**
// * <p>User: Zhang Kaitao
// * <p>Date: 14-1-3
// * <p>Version: 1.0
// */
//public class DynamicDeployBeans2 {
//
//    protected static final Log logger = LogFactory.getLog(DynamicDeployBeans2.class);
//
//    //RequestMappingHandlerMapping
//    private static Method detectHandlerMethodsMethod =
//            ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "detectHandlerMethods", Object.class);
//    private static Method getMappingForMethodMethod =
//            ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingForMethod", Method.class, Class.class);
//    private static Method getMappingPathPatternsMethod =
//            ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getMappingPathPatterns", RequestMappingInfo.class);
//    private static Method getPathMatcherMethod =
//            ReflectionUtils.findMethod(RequestMappingHandlerMapping.class, "getPathMatcher");
//    private static Field handlerMethodsField =
//            ReflectionUtils.findField(RequestMappingHandlerMapping.class, "handlerMethods", Map.class);
//    private static Field urlMapField =
//            ReflectionUtils.findField(RequestMappingHandlerMapping.class, "urlMap", MultiValueMap.class);
//
//
//    private static final String SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME =
//            "org.springframework.scripting.config.scriptFactoryPostProcessor";
//
//    private Long refreshCheckDelay = -1L;
//
//    static {
//        detectHandlerMethodsMethod.setAccessible(true);
//        getMappingForMethodMethod.setAccessible(true);
//        getMappingPathPatternsMethod.setAccessible(true);
//        getPathMatcherMethod.setAccessible(true);
//        handlerMethodsField.setAccessible(true);
//        urlMapField.setAccessible(true);
//    }
//
//
//    private ApplicationContext ctx;
//    private DefaultListableBeanFactory beanFactory;
//
//    private boolean hasRegisterScriptFactoryPostProcessor = false;
//
//
//    @Autowired
//    public void setApplicationContext(ApplicationContext ctx) {
//        if (!DefaultListableBeanFactory.class.isAssignableFrom(ctx.getAutowireCapableBeanFactory().getClass())) {
//            throw new IllegalArgumentException("BeanFactory must be DefaultListableBeanFactory type");
//        }
//        this.ctx = ctx;
//        this.beanFactory = (DefaultListableBeanFactory) ctx.getAutowireCapableBeanFactory();
//    }
//
//    public void setRefreshCheckDelay(Long refreshCheckDelay) {
//        this.refreshCheckDelay = refreshCheckDelay;
//    }
//
//    public void registerBean(Class<?> beanClass) {
//        registerBean(null, beanClass);
//    }
//
//    public void registerBean(String beanName, Class<?> beanClass) {
//        Assert.notNull(beanClass, "register bean class must not null");
//        GenericBeanDefinition bd = new GenericBeanDefinition();
//        bd.setBeanClass(beanClass);
//
//        if (StringUtils.hasText(beanName)) {
//            beanFactory.registerBeanDefinition(beanName, bd);
//        } else {
//            BeanDefinitionReaderUtils.registerWithGeneratedName(bd, beanFactory);
//        }
//
//    }
//
//    public void registerController(Class<?> controllerClass) {
//        Assert.notNull(controllerClass, "register controller bean class must not null");
//        if (!WebApplicationContext.class.isAssignableFrom(ctx.getClass())) {
//            throw new IllegalArgumentException("applicationContext must be WebApplicationContext type");
//        }
//
//        GenericBeanDefinition beanDefinition = new GenericBeanDefinition();
//        beanDefinition.setBeanClass(controllerClass);
//
//        String controllerBeanName =
//                BeanDefinitionReaderUtils.registerWithGeneratedName(beanDefinition, beanFactory);
//
//        addHandler(controllerBeanName);
//    }
//
//
//    public void registerGroovyController(String scriptLocation) {
//        registerScriptFactoryPostProcessorIfNecessary();
//        // Create script factory bean definition.
//        GenericBeanDefinition bd = new GenericBeanDefinition();
//        bd.setBeanClassName(GroovyScriptFactory.class.getName());
//
//        bd.setAttribute(ScriptFactoryPostProcessor.LANGUAGE_ATTRIBUTE, "groovy");
//        bd.setAttribute(ScriptFactoryPostProcessor.REFRESH_CHECK_DELAY_ATTRIBUTE, refreshCheckDelay);
//
//        bd.setAttribute(ScriptFactoryPostProcessor.PROXY_TARGET_CLASS_ATTRIBUTE, true);
//
//        ConstructorArgumentValues cav = bd.getConstructorArgumentValues();
//        int constructorArgNum = 0;
//        cav.addIndexedArgumentValue(constructorArgNum++, scriptLocation);
//
//        String controllerBeanName = scriptLocation;
//        beanFactory.registerBeanDefinition(controllerBeanName, bd);
//        addHandler(controllerBeanName);
//    }
//
//
//    private void addHandler(String controllerBeanName) {
//        RequestMappingHandlerMapping requestMappingHandlerMapping = requestMappingHandlerMapping();
//
//        //remove old
//        Class<?> handlerType = ctx.getType(controllerBeanName);
//        final Class<?> userType = ClassUtils.getUserClass(handlerType);
//
//        Map handlerMethods = (Map) ReflectionUtils.getField(handlerMethodsField, requestMappingHandlerMapping);
//        MultiValueMap urlMapping = (MultiValueMap) ReflectionUtils.getField(urlMapField, requestMappingHandlerMapping);
//
//        final RequestMappingHandlerMapping innerRequestMappingHandlerMapping = requestMappingHandlerMapping;
//        Set<Method> methods = HandlerMethodSelector.selectMethods(userType, new ReflectionUtils.MethodFilter() {
//            @Override
//            public boolean matches(Method method) {
//                return ReflectionUtils.invokeMethod(
//                        getMappingForMethodMethod,
//                        innerRequestMappingHandlerMapping,
//                        method, userType) != null;
//            }
//        });
//
//        for (Method method : methods) {
//            RequestMappingInfo mapping =
//                    (RequestMappingInfo) ReflectionUtils.invokeMethod(getMappingForMethodMethod, requestMappingHandlerMapping, method, userType);
//            handlerMethods.remove(mapping);
//
//            Set<String> patterns =
//                    (Set<String>) ReflectionUtils.invokeMethod(getMappingPathPatternsMethod, requestMappingHandlerMapping, mapping);
//
//            PathMatcher pathMatcher =
//                    (PathMatcher) ReflectionUtils.invokeMethod(getPathMatcherMethod, requestMappingHandlerMapping);
//
//            for (String pattern : patterns) {
//                if (!pathMatcher.isPattern(pattern)) {
//                    urlMapping.remove(pattern);
//                }
//            }
//        }
//
//        //spring 3.1 开始
//        ReflectionUtils.invokeMethod(detectHandlerMethodsMethod, requestMappingHandlerMapping, controllerBeanName);
//
//
//    }
//
//    private RequestMappingHandlerMapping requestMappingHandlerMapping() {
//        try {
//            return ctx.getBean(RequestMappingHandlerMapping.class);
//        } catch (Exception e) {
//            throw new IllegalArgumentException("applicationContext must has RequestMappingHandlerMapping");
//        }
//    }
//
//
//    private void registerScriptFactoryPostProcessorIfNecessary() {
//        if (!hasRegisterScriptFactoryPostProcessor) {
//            hasRegisterScriptFactoryPostProcessor = beanFactory.containsBeanDefinition(SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME);
//            if (!hasRegisterScriptFactoryPostProcessor) {
//                BeanDefinition beanDefinition = new RootBeanDefinition(ScriptFactoryPostProcessor.class);
//                beanFactory.registerBeanDefinition(SCRIPT_FACTORY_POST_PROCESSOR_BEAN_NAME, beanDefinition);
//                beanFactory.addBeanPostProcessor(beanFactory.getBean(ScriptFactoryPostProcessor.class));
//
//            }
//        }
//    }
//
//}
//	